package com.woniuxy.boot.common.util;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class EntityConverter {
    public static <T> T convert(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }

        try {
            T target = targetClass.getDeclaredConstructor().newInstance();
            Map<String, Field> targetFieldMap = getFieldMap(targetClass);

            for (Field sourceField : source.getClass().getDeclaredFields()) {
                sourceField.setAccessible(true);
                String fieldName = sourceField.getName();
                if (targetFieldMap.containsKey(fieldName)) {
                    Field targetField = targetFieldMap.get(fieldName);
                    targetField.setAccessible(true);

                    // Check type compatibility before setting value
                    if (isTypeCompatible(sourceField.getType(), targetField.getType())) {
                        Object value = sourceField.get(source);
                        if (value != null) {
                            targetField.set(target, value);
                        }
                    }
                }
            }

            return target;
        } catch (Exception e) {
            throw new RuntimeException("转换失败", e);
        }
    }

    private static boolean isTypeCompatible(Class<?> sourceType, Class<?> targetType) {
        // Simple type compatibility check; can be extended as needed
        return targetType.isAssignableFrom(sourceType) ||
                (sourceType.isPrimitive() && wrapperTypeForPrimitive(sourceType) == targetType) ||
                (targetType.isPrimitive() && primitiveTypeForWrapper(targetType) == sourceType);
    }

    private static Class<?> wrapperTypeForPrimitive(Class<?> primitiveType) {
        if (primitiveType == int.class) return Integer.class;
        else if (primitiveType == boolean.class) return Boolean.class;
        else if (primitiveType == long.class) return Long.class;
        else if (primitiveType == double.class) return Double.class;
        else if (primitiveType == float.class) return Float.class;
        else if (primitiveType == short.class) return Short.class;
        else if (primitiveType == byte.class) return Byte.class;
        else if (primitiveType == char.class) return Character.class;
        return null;
    }

    private static Class<?> primitiveTypeForWrapper(Class<?> wrapperType) {
        if (wrapperType == Integer.class) return int.class;
        else if (wrapperType == Boolean.class) return boolean.class;
        else if (wrapperType == Long.class) return long.class;
        else if (wrapperType == Double.class) return double.class;
        else if (wrapperType == Float.class) return float.class;
        else if (wrapperType == Short.class) return short.class;
        else if (wrapperType == Byte.class) return byte.class;
        else if (wrapperType == Character.class) return char.class;
        return null;
    }

    private static Map<String, Field> getFieldMap(Class<?> clazz) {
        Map<String, Field> fieldMap = new HashMap<>();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            fieldMap.put(field.getName(), field);
        }
        return fieldMap;
    }
}
